<dom-module id="grid-selection-demos">
  <template>
    <style include="vaadin-component-demo-shared-styles">
      :host {
        display: block;
      }
    </style>

    <h3>Selecting Items</h3>
    <p>
      <code>&lt;vaadin-grid&gt;</code> ships with a helper element <code>&lt;vaadin-grid-selection-column&gt;</code>
      that renders checkboxes bound to the selection state of the grid on every row.
      It also adds a "select all" checkbox to the column header when <code>items</code> array is used
      as the grid's data source.
    </p>
    <p>
      The selected items can be accessed through the grid's <code>selectedItems</code> property. Each time
      the selection state changes, grid dispatches a "selected-items-changed" event.
    </p>
    <p>
      <b>Hint:</b> Use <code>autoSelect</code> to enable selecting rows on click.
    </p>
    <p>
      <b>NOTE: You must explicitly import the <code>vaadin-grid-selection-column</code> in order to use it.</b>
    </p>
    <vaadin-demo-snippet id="grid-selection-demos-selecting" when-defined="vaadin-grid">
      <template preserve-content>
        <vaadin-grid aria-label="Multi-Selection Example">
          <vaadin-grid-selection-column auto-select></vaadin-grid-selection-column>
          <vaadin-grid-column path="name.first" header="First name"></vaadin-grid-column>
          <vaadin-grid-column path="name.last" header="Last name"></vaadin-grid-column>
          <vaadin-grid-column path="email"></vaadin-grid-column>
        </vaadin-grid>

        <script>
          window.addDemoReadyListener('#grid-selection-demos-selecting', function(document) {
            document.querySelector('vaadin-grid').items = Vaadin.GridDemo.users;
          });
        </script>
      </template>
    </vaadin-demo-snippet>

    <h3>Manual Selection with Active Item</h3>
    <p>
      When a row is clicked or the space key is pressed while a row cell is in focus,
      the related item object is assigned as the grid's <code>activeItem</code>.
    </p>
    <p>
      To programmatically select items, the <code>activeItem</code>, for example, could be
      added to the grid's <code>selectedItems</code> array.
      The methods <code>selectItem(item)</code> and <code>deselectItem(item)</code> can also be used
      to select or deselect items.
    </p>
    <p>
      In the example below, the grid's <code>selectedItems</code> array is replaced
      whenever <code>activeItem</code> changes, making it single-selectable.
    </p>
    <vaadin-demo-snippet id="grid-selection-demos-selection-using-active-item" when-defined="vaadin-grid">
      <template preserve-content>
        <vaadin-grid aria-label="Selection using Active Item Example">
          <vaadin-grid-column path="name.first" header="First name"></vaadin-grid-column>
          <vaadin-grid-column path="name.last" header="Last name"></vaadin-grid-column>
          <vaadin-grid-column path="email"></vaadin-grid-column>
        </vaadin-grid>
        <script>
          window.addDemoReadyListener('#grid-selection-demos-selection-using-active-item', function(document) {
            const grid = document.querySelector('vaadin-grid');

            grid.addEventListener('active-item-changed', function(event) {
              const item = event.detail.value;
              grid.selectedItems = item ? [item] : [];
            });

            grid.items = Vaadin.GridDemo.users;
          });
        </script>
      </template>
    </vaadin-demo-snippet>

    <h3>Custom Selection with Data Provider</h3>
    <p>
      When dealing with remote data, "selecting all" can get tricky when it comes to
      reflecting the full data set to the grid's <code>selectedItems</code> array.
    </p>
    <p>
      In this example, a custom selection state is used to implement "select all"
      functionality without having to include all the items to <code>selectedItems</code>.
    </p>
    <p>
      The <code>selected</code> property of the <code>model</code> renderer parameter is used
      here to reflect the item's selection state to a checkbox on the corresponding row.
    </p>
    <vaadin-demo-snippet id="grid-selection-demos-custom-select-all-with-data-provider" when-defined="vaadin-grid">
      <template preserve-content>
        <vaadin-grid aria-label="Select All with Data Example">
          <vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
          <vaadin-grid-column path="firstName" header="First name"></vaadin-grid-column>
          <vaadin-grid-column path="lastName" header="Last name"></vaadin-grid-column>
        </vaadin-grid>
        <script>
          window.addDemoReadyListener('#grid-selection-demos-custom-select-all-with-data-provider', function(document) {
            let inverted = false, indeterminate = false;

            const grid = document.querySelector('vaadin-grid');
            grid.size = 200;
            grid.dataProvider = function(params, callback) {
              var xhr = new XMLHttpRequest();
              xhr.onload = function() {
                callback(JSON.parse(xhr.responseText).result);
              };
              var index = params.page * params.pageSize;
              xhr.open('GET', 'https://demo.vaadin.com/demo-data/1.0/people?index=' + index + '&count=' + params.pageSize, true);
              xhr.send();
            };

            const column = grid.querySelector('vaadin-grid-column');

            column.headerRenderer = function(cell) {
              var checkbox = cell.firstElementChild;
              if (!checkbox) {
                checkbox = window.document.createElement('vaadin-checkbox');
                checkbox.setAttribute('aria-label', 'Select All');
                checkbox.setAttribute('style', 'font-size: var(--lumo-font-size-m)');
                checkbox.addEventListener('change', function(e) {
                  grid.selectedItems = [];
                  inverted = !inverted;
                  indeterminate = false;
                  grid.render();
                });
                cell.appendChild(checkbox);
              }
              checkbox.checked = indeterminate || inverted;
              checkbox.indeterminate = indeterminate;
            };

            column.renderer = function(cell, column, model) {
              var checkbox = cell.firstElementChild;
              if (!checkbox) {
                checkbox = window.document.createElement('vaadin-checkbox');
                checkbox.setAttribute('aria-label', 'Select Row');
                checkbox.addEventListener('change', function(e) {
                  if (e.target.checked === inverted) {
                    grid.deselectItem(checkbox.__item);
                  } else {
                    grid.selectItem(checkbox.__item);
                  }
                  indeterminate = grid.selectedItems.length > 0;
                  grid.render();
                });
                cell.appendChild(checkbox);
              }
              checkbox.__item = model.item;
              checkbox.checked = inverted !== model.selected;
            };
          });
        </script>
      </template>
    </vaadin-demo-snippet>

    <h3>Space Key Action and Click to Activate</h3>
    <p>
      When a focused cell has child elements, the <kbd>Space</kbd> key clicks
      the first child element.
    </p>
    <p>
      Clicking a child element inside a cell activates the item, unless either:
    </p>
    <ul>
      <li>
        The clicked child is a focusable element, for example,
        an <code>&lt;input&gt;</code>, a <code>&lt;button&gt;</code>, or has
        the <code>tabindex</code> attribute.
      </li>
      <li>The clicked child prevents default action of the <code>click</code> event.</li>
      <li>The clicked child stops propagation of the <code>click</code> event.</li>
    </ul>
    <p>
      Try clicking and pressing <kbd>Space</kbd> for the body cell contents
      in the example below.
    </p>
    <vaadin-demo-snippet id="grid-selection-demos-space-key-action-and-click-to-activate" when-defined="vaadin-grid">
      <template preserve-content>
        <vaadin-grid aria-label="Space Key Action Example">
          <vaadin-grid-column></vaadin-grid-column>
          <vaadin-grid-column></vaadin-grid-column>
          <vaadin-grid-column></vaadin-grid-column>
          <vaadin-grid-column></vaadin-grid-column>
        </vaadin-grid>
        <script>
          window.addDemoReadyListener('#grid-selection-demos-space-key-action-and-click-to-activate', function(document) {
            const grid = document.querySelector('vaadin-grid');

            grid.items = Array.from(new Array(200)).map(function(item, index) {
              return {index: index};
            });

            const columns = document.querySelectorAll('vaadin-grid-column');

            columns[0].renderer = function(root, column, model) {
              root.textContent = 'Space activates';
            };

            columns[1].renderer = function(root, column, model) {
              root.innerHTML = '';
              const alertBtn = window.document.createElement('button');
              alertBtn.textContent = 'Button';
              alertBtn.addEventListener('click', function(event) {
                alert(event.target.textContent + ' clicked');
              });
              const textNode = window.document.createTextNode('Space does not activate');

              root.appendChild(alertBtn);
              root.appendChild(textNode);
            };

            columns[2].renderer = function(root, column, model) {
              root.innerHTML = '';
              const alertBlock = window.document.createElement('div');
              alertBlock.textContent = 'Div';
              alertBlock.addEventListener('click', function(event) {
                alert(event.target.textContent + ' clicked');
              });
              const textNode = window.document.createTextNode('Space activates');

              root.appendChild(alertBlock);
              root.appendChild(textNode);
            };

            columns[3].renderer = function(root, column, model) {
              root.innerHTML = '';
              const alertBlock = window.document.createElement('div');
              alertBlock.textContent = 'Div with preventDefault';
              alertBlock.addEventListener('click', function(event) {
                event.preventDefault();
                alert(event.target.textContent + ' clicked');
              });
              const textNode = window.document.createTextNode('Space does not activate');

              root.appendChild(alertBlock);
              root.appendChild(textNode);

            };

            columns[0].headerRenderer = function(root) {
              root.textContent = 'Only text contents';
            };

            columns[1].headerRenderer = function(root) {
              root.textContent = 'Button first child';
            };

            columns[2].headerRenderer = function(root) {
              root.textContent = 'Div first child';
            };

            columns[3].headerRenderer = function(root) {
              root.textContent = 'preventDefault for click';
            };

            grid.addEventListener('active-item-changed', function(event) {
              const item = event.detail.value;
              grid.selectedItems = item ? [item] : [];
            });
          });
        </script>
      </template>
    </vaadin-demo-snippet>

    <h3>Selection using Templates</h3>
    <p>
      In addition to modifying selection using <code>selectedItems</code> property
      or <code>selectItem(item)</code> and <code>deselectItem(item)</code> methods,
      with Polymer templates, the instance property <code>{{selected}}</code> can also be
      toggled to apply selection.
    </p>
    <vaadin-demo-snippet id="grid-selection-demos-selection-using-templates" when-defined="vaadin-grid">
      <template preserve-content>
        <dom-bind>
          <template>
            <x-data-provider data-provider="{{dataProvider}}"></x-data-provider>

            <vaadin-grid aria-label="Selection using Templates Example" data-provider="[[dataProvider]]" size="200">
              <vaadin-grid-column width="60px" flex-grow="0">
                <template class="header">#</template>
                <template>[[index]]</template>
              </vaadin-grid-column>

              <vaadin-grid-column>
                <template class="header">First name</template>
                <template>[[item.name.first]]</template>
              </vaadin-grid-column>

              <vaadin-grid-column>
                <template class="header">Last name</template>
                <template>[[item.name.last]]</template>
              </vaadin-grid-column>

              <vaadin-grid-column>
                <template>
                  <vaadin-checkbox aria-label="Select Row" checked="{{selected}}">Selected</vaadin-checkbox>
                </template>
              </vaadin-grid-column>
            </vaadin-grid>
          </template>
        </dom-bind>
      </template>
    </vaadin-demo-snippet>

  </template>
  <script>
    class GridSelectionDemos extends DemoReadyEventEmitter(GridDemo(Polymer.Element)) {
      static get is() {
        return 'grid-selection-demos';
      }
    }
    customElements.define(GridSelectionDemos.is, GridSelectionDemos);
  </script>
</dom-module>
